<template>
	<view class="content">
		<view style="" class="topvg">
			<view style="width: 100%;display: flex;justify-content: center;padding: 50rpx;flex-direction: column;align-items: center;">
				<u-loading v-if="status == 'applying'" color="#7fbebe"></u-loading>
				<view style="color: #7fbebe;font-size: 30rpx;margin-top: 10rpx;" v-if="status == 'applying'">连麦申请中..</view>
				<view v-if="status == 'lming'" style="width: 100%;display: flex;justify-content: flex-start;">
					<view @click="changecamera" class="btnitem" style="margin: 1rpx;">
						<image src="/static/images/qqhsxt.png" style="width: 60rpx;" mode="widthFix"></image>
					</view>
				</view>
			</view>
		</view>
		
		<view style="width: 100%;display: flex;flex-wrap: wrap;flex: 1;overflow-y: hidden;">
			<bgyx-video-item :uid="uid" name="name" id="bgyx_video_1" :src="uservddata.stream" status="play"
				:video="uservddata.video" :audio="uservddata.audio" />

		</view>
		
		<view style="width: 250rpx;display: flex;flex-direction: column;align-items: center;position: fixed;right: 25rpx;top: 60rpx;z-index: 108;padding: 15rpx;height: 70vh;overflow-y: auto;">
			<view v-if="myvddata && myvddata.stream" style="width: 100%;display: flex;padding: 15rpx;flex-direction: column;align-items: center;border-radius: 12rpx;background: #bec7df66;color: #dae3f7;margin-bottom: 15rpx;">
				<view v-if="!myvddata.video" style="width: 100%;display: flex;flex-direction: column;align-items: center;">
					<bgyx-user-avatar :id="$store.state.user.user.id" />
					<view style="font-size: 20rpx;margin-top: 10rpx;">
						{{$store.state.user.user.name}}
					</view>
					<view style="width: 100%;display: flex;justify-content: center;align-items: center;margin-top: 5rpx;">
						
					</view>
				</view>
				<view v-else style="width: 100%;height: 300rpx;border-radius: 12rpx;">
					<bgyx-video-small :uid="$store.state.user.user.id" :name="$store.state.user.user.name" id="bgyx_video_0" :src="myvddata.stream" status="play"
						:video="myvddata.video" :audio="myvddata.audio" />
				</view>
			</view>
			<view style="width: 100%;display: flex;padding: 15rpx;flex-direction: column;align-items: center;border-radius: 12rpx;background: #bec7df66;color: #dae3f7;margin-bottom: 15rpx;" v-for="(item,k) in lmusers">
				<view v-if="!item.video" style="width: 100%;display: flex;flex-direction: column;align-items: center;">
					<bgyx-user-avatar :id="item.id" />
					<view style="font-size: 20rpx;margin-top: 10rpx;">
						{{item.name}}
					</view>
					<view style="width: 100%;display: flex;justify-content: center;align-items: center;margin-top: 5rpx;">
						
					</view>
				</view>
				<view v-else style="width: 100%;height: 300rpx;border-radius: 12rpx;">
					<bgyx-video-small :uid="item.id" :name="item.name" :id="`bgyx_lmv${item.id}`" :src="item.stream" status="play"
						:video="item.video" :audio="item.audio" />
				</view>
			</view>
		</view>

		<view style="z-index: 109;" class="btmvg" v-if="status == 'normal' || status == 'applying'">
			<view style="display: flex;width: 100%;align-items: center;justify-content: center;margin-bottom: 60rpx;">
				
				<view @click="exit" class="btnitem"
					style="margin: 40rpx;background: #ff5e5e;">
					<image src="/static/images/hhdown.png" style="width: 60rpx;" mode="widthFix"></image>
				</view>
		
				<view @click="applylm" v-if="status == 'normal'" class="btnitem" style="margin: 40rpx;">
					<image src="/static/images/ssqlm.png" style="width: 60rpx;" mode="widthFix"></image>
				</view>
				
				<view @click="closelm" v-if="status == 'applying'" class="btnitem" style="margin: 40rpx;">
					<image src="/static/images/ggb.png" style="width: 50rpx;height: 50rpx;" mode="widthFix"></image>
				</view>
			</view>
		</view>
		
		<view style="z-index: 109;" class="btmvg" v-if="status == 'lming'">
			<view style="display: flex;width: 100%;align-items: center;justify-content: center;margin-bottom: 60rpx;">
				
				
				<view @click="changeaudio(false)" v-if="myvddata.audio" class="btnitem" style="margin: 15rpx;">
					<image src="/static/images/mmic.png" style="width: 60rpx;" mode="widthFix"></image>
				</view>
				<view @click="changeaudio(true)" v-if="!myvddata.audio" class="btnitem" style="background: #ff5e5e66;margin: 15rpx;">
					<image src="/static/images/mmic.png" style="width: 60rpx;" mode="widthFix"></image>
				</view>
				
				<view @click="changevideo(false)" v-if="myvddata.video" class="btnitem" style="margin:15rpx;">
					<image src="/static/images/ccamera.png" style="width: 60rpx;" mode="widthFix"></image>
				</view>
				<view @click="changevideo(true)" v-if="!myvddata.video" class="btnitem"
					style="margin:15rpx;background: #ff5e5e66;">
					<image src="/static/images/ccamera.png" style="width: 60rpx;" mode="widthFix"></image>
				</view>
		
				<view @click="exit" class="btnitem"
					style="margin: 15rpx;background: #ff5e5e;">
					<image src="/static/images/hhdown.png" style="width: 60rpx;" mode="widthFix"></image>
				</view>
		
				
				<view @click="closelmx" class="btnitem" style="margin: 15rpx;">
					<image src="/static/images/ggb.png" style="width: 50rpx;height: 50rpx;" mode="widthFix"></image>
				</view>
			</view>
		</view>
		
	</view>
</template>

<script>
	import config from '../../config.js'
	import {
		mapState
	} from 'vuex';
	import {
		pub,
		sub,
		unsub
	} from '../../common/event';
	import moment from 'moment/moment';
	export default {
		data() {
			return {
				id: '',
				name: '',
				src: '',
				showself: true,
				myvddata: '',
				uservddata: '',
				audio: true,
				video: true,
				info:'',
				status:"normal",
				applyt:0,
				lmusers:[]
			}
		},
		components: {

		},
		computed: {
			...mapState({
				
			})
		},
		onBackPress(options) {
			console.log(147, options)
			if (options.from && options.from == 'backbutton') {
				return true
			}
			return false
		},
		onUnload() {
			unsub("socket_touser_applyret_agree",this.applylmagree)
			unsub("socket_touser_applyret_refuse",this.applylmrefuse)
			unsub("socket_liveroomlmenter",this.livetoomlmenter)
			unsub("socket_liveroomchange",this.liveroomchange)
			unsub("socket_liveroomremoveuser",this.liveroomremoveuser)
			unsub(`socket_lmuserleave_${this.uid}`,this.lmuserleave)
			unsub(`socket_lmuserchangeinfo_${this.uid}`,this.lmuserchangeinfo)
			unsub(`socket_liveroomstop`,this.liveroomstop)
			this.$store.commit(`common/setStatus`,'normal')
		},
		onLoad({
			id,uid
		}) {
			sub("socket_touser_applyret_agree",this.applylmagree)
			sub("socket_touser_applyret_refuse",this.applylmrefuse)
			sub("socket_liveroomlmenter",this.livetoomlmenter)
			sub("socket_liveroomchange",this.liveroomchange)
			sub("socket_liveroomremoveuser",this.liveroomremoveuser)
			sub(`socket_lmuserleave_${uid}`,this.lmuserleave)
			sub(`socket_lmuserchangeinfo_${uid}`,this.lmuserchangeinfo)
			sub(`socket_liveroomstop`,this.liveroomstop)
			this.$store.commit(`common/setStatus`,'videocall')
			
			this.id = id
			this.uid = uid
			this.getData()
		},
		methods: {
			applylmagree:function(){
				uni.showToast({
					title:"连麦申请通过",
				})
				this.status = "lming"
				this.publishStream({
					video:true,
					audio:true,
					videoType:'face'
				})
			},
			applylmrefuse:function(){
				uni.showToast({
					title:"连麦申请被拒绝",
					icon:"none"
				})
				this.status = "normal"
			},
			livetoomlmenter:function(e){
				const user = this.$store.state.user.user
				if(e.uid == this.uid && e.id == this.id && user.id != e.user.id){
					this.subLmStream(e.user)
				}
			},
			liveroomchange:function(e){
				if(e.uid != this.uid){
					return
				}
				if(e.uid == this.uid){
					this.uservddata.video = e.video
					this.uservddata.audio = e.audio
				}
			},
			lmuserchangeinfo: async function(e){
				const user = this.$store.state.user.user
				if(e.user.id != user.id){
					for(let o of this.lmusers){
						if(o.id == e.user.id){
							o.video = e.data.video
							o.audio = e.data.audio
							break
						}
					}
				}
			},
			liveroomstop: async function(e){
				const _this = this
				uni.showModal({
					title:"直播结束",
					content:"直播已结束，下次再来吧~",
					success() {
						_this.exit()   
					}
				})
			},
			lmuserleave: async function(e){
				const user = this.$store.state.user.user
				if(e.id != user.id){
					for(let o of this.lmusers){
						if(o.id == e.id){
							await o.close()
							break
						}
					}
					this.lmusers = this.lmusers.filter(ex=>ex.id != e.id)
				}
			},
			liveroomremoveuser:async function(e){
				if(e.id != this.uid){
					return
				}
				const user = this.$store.state.user.user
				if(e.user.id == user.id){
					try{
						// await this.myvddata.unpublish()
						this.closelmx()
					}catch(e){
						//TODO handle the exception
					}
				}else{
					for(let o of this.lmusers){
						if(o.id == e.user.id){
							try{
								await o.close()
							}catch(e){
								//TODO handle the exception
							}
							break
						}
					}
					this.lmusers = this.lmusers.filter(ex=>ex.id != e.user.id)
				}
			},
			closelmx:async function(){
				this.status = 'normal'
				try{
					await this.myvddata.unpublish()
				}catch(e){
					//TODO handle the exception
				}
				this.$u.post(`chat/chat/liveroom/closeapplylmx/${this.uid}`)
				
				uni.showToast({
					title:"连麦已结束"
				})
				
			},
			closelm:async function(){
				this.status = 'normal'
				
				this.$u.post(`chat/chat/liveroom/closeapplylm/${this.uid}`)
				
				uni.showToast({
					title:"连麦申请已取消"
				})
				
			},
			applylm:async function(){
				if(this.status == 'applying'){
					uni.showToast({
						title:"请勿频繁申请连麦",
						icon:"none"
					})
					return
				}
				const n = moment().valueOf()
				if( (n - this.applyt) < 1000 * 100 ){
					uni.showToast({
						title:"请勿频繁申请连麦",
						icon:"none"
					})
					return
				}
				this.status = 'applying'
				this.applyt = n
				
				this.$u.post(`chat/chat/liveroom/applylm/${this.uid}`)
				
				uni.showToast({
					title:"连麦申请已发送"
				})
				
			},
			getData:async function(){
				const ret = await this.$u.get(`chat/chat/getdata/liveroom/${this.id}`)
				this.info = ret.data
				this.subStream()
				// this.publishStream({
				// 	video:true,
				// 	audio:true,
				// })
				
				if(ret.data && ret.data.lmusers){
					for(let o of ret.data.lmusers){
						this.subLmStream(o)
					}
				}
			},
			changecamera: async function() {
				let videoType = this.myvddata.videoType
				if(videoType == "face"){
					videoType = "environment"
				}else{
					videoType = "face"
				}
				try{
					await this.myvddata.unpublish()
					this.publishStreamc({
						videoType,
						video:this.myvddata.video,
						audio:this.myvddata.audio,
					})
				}catch(e){
					//TODO handle the exception
				}
			},
			changeuseraudio: function(e) {
				this.uservddata.audio = e.audio
			},
			changeuservideo: function(e) {
				this.uservddata.video = e.video
			},
			changeaudio: function(e) {
				this.myvddata.muteAudio(e)
				this.myvddata.audio = e
				this.$u.put(`chat/chat/lmuserchangeinfo/${this.uid}`,{
					video:this.myvddata.video,
					audio:this.myvddata.audio
				})
			},
			changevideo: function(e) {
				this.myvddata.muteVideo(e)
				this.myvddata.video = e
				this.$u.put(`chat/chat/lmuserchangeinfo/${this.uid}`,{
					video:this.myvddata.video,
					audio:this.myvddata.audio
				})
			},
			closeall: async function(e) {
				try {
					await this.myvddata.unpublish()
					await this.uservddata.close()
				} catch (e) {
					//TODO handle the exception
				}
				uni.navigateBack()
			},
			exit: async function(e) {
				try {
					if(this.myvddata){
						await this.myvddata.unpublish()
					}
					if(this.uservddata){
						await this.uservddata.close()
					}
					
					for(let o of this.lmusers){
						await o.close()
					}
				} catch (e) {
					//TODO handle the exception
				}
				this.$store.commit(`common/setStatus`,'normal')
				this.$u.post(`chat/chat/leaveliveroom/${this.uid}`)
				uni.navigateBack()
			},
			handlesingle: async function(e) {
				this.subStream()
			},
			subStream: async function() {
				const roomId = "liveroom"
				const id = this.uid
				const pc = new RTCPeerConnection(null);
				pc.addTransceiver('audio', {
					direction: 'recvonly'
				});
				pc.addTransceiver('video', {
					direction: 'recvonly'
				});
				let offer = await pc.createOffer();
				let stream = new MediaStream();
				pc.ontrack = function(event) {
					console.log(event);
					stream.addTrack(event.track);
				};
				await pc.setLocalDescription(offer);
				let session = await new Promise(function(resolve, reject) {
					let data = {
						api: `${config.srsUrl}/rtc/v1/play/`,
						tid: id,
						streamurl: `webrtc://${config.ip}/${roomId}/${id}`,
						clientip: null,
						sdp: offer.sdp,
					};
					console.log('Generated offer: ', data);
			
					const xhr = new XMLHttpRequest();
					xhr.onload = function() {
						if (xhr.readyState !== xhr.DONE) return;
						if (xhr.status !== 200) return reject(xhr);
						const data = JSON.parse(xhr.responseText);
						console.log('Got answer: ', data);
						return data.code ? reject(xhr) : resolve(data);
					};
					xhr.open('POST', `${config.srsUrl}/rtc/v1/play/`, true);
					xhr.setRequestHeader('Content-type', 'application/json');
					xhr.send(JSON.stringify(data));
				});
				await pc.setRemoteDescription(
					new RTCSessionDescription({
						type: 'answer',
						sdp: session.sdp
					}),
				);
			
				function close() {
					stream.getTracks().forEach(function(track) {
						track.stop();
						stream.removeTrack(track);
					});
					// stream.close()
					pc.close();
				}
			
				const vdata = {
					id,
					roomId,
					pc,
					stream,
					audio: true,
					video: true,
					close,
				};
			
				this.uservddata = vdata
				
			},
			subLmStream: async function(item) {
				const roomId = "liveroomlm"+this.uid
				const id = item.id
				const pc = new RTCPeerConnection(null);
				pc.addTransceiver('audio', {
					direction: 'recvonly'
				});
				pc.addTransceiver('video', {
					direction: 'recvonly'
				});
				let offer = await pc.createOffer();
				let stream = new MediaStream();
				pc.ontrack = function(event) {
					console.log(event);
					stream.addTrack(event.track);
				};
				await pc.setLocalDescription(offer);
				let session = await new Promise(function(resolve, reject) {
					let data = {
						api: `${config.srsUrl}/rtc/v1/play/`,
						tid: id,
						streamurl: `webrtc://${config.ip}/${roomId}/${id}`,
						clientip: null,
						sdp: offer.sdp,
					};
					console.log('Generated offer: ', data);

					const xhr = new XMLHttpRequest();
					xhr.onload = function() {
						if (xhr.readyState !== xhr.DONE) return;
						if (xhr.status !== 200) return reject(xhr);
						const data = JSON.parse(xhr.responseText);
						console.log('Got answer: ', data);
						return data.code ? reject(xhr) : resolve(data);
					};
					xhr.open('POST', `${config.srsUrl}/rtc/v1/play/`, true);
					xhr.setRequestHeader('Content-type', 'application/json');
					xhr.send(JSON.stringify(data));
				});
				await pc.setRemoteDescription(
					new RTCSessionDescription({
						type: 'answer',
						sdp: session.sdp
					}),
				);

				function close() {
					stream.getTracks().forEach(function(track) {
						track.stop();
						stream.removeTrack(track);
					});
					// stream.close()
					pc.close();
				}

				const vdata = {
					id,
					roomId,
					pc,
					stream,
					audio: item.audio,
					video: item.video,
					close,
				};

				this.lmusers.push(vdata)
				
			},
			publishStream: async function(options) {
				const id = this.$store.state.user.user.id
				const roomId = 'liveroomlm'+this.uid
				const pc = new RTCPeerConnection(null);
				pc.addTransceiver('audio', {
					direction: 'sendonly'
				});
				pc.addTransceiver('video', {
					direction: 'sendonly'
				});
				const stream = await this.getStreamLoc({
					audio: true,
					video: {
						facingMode: options.videoType ? options.videoType : "environment"
					},
				})
				this.cameraType = options.videoType ? options.videoType : "environment"
				console.log(stream);
				stream.getTracks().forEach(function(track) {
					pc.addTrack(track);
					if (track.kind === 'audio') {
						if (options.audio === false) {
							track.enabled = false;
						}
					}
					if (track.kind === 'video') {
						if (options.video === false) {
							track.enabled = false;
						}
					}
				});
				let offer = await pc.createOffer();
				await pc.setLocalDescription(offer);
			
				let session = await new Promise(function(resolve, reject) {
					let data = {
						api: `${config.srsUrl}/rtc/v1/publish/`,
						tid: id,
						streamurl: `webrtc://${config.ip}/${roomId}/${id}`,
						clientip: null,
						sdp: offer.sdp,
					};
					console.log('Generated offer: ', data);
			
					const xhr = new XMLHttpRequest();
					xhr.onload = function() {
						if (xhr.readyState !== xhr.DONE) return;
						if (xhr.status !== 200) return reject(xhr);
						const data = JSON.parse(xhr.responseText);
						console.log('Got answer: ', data);
						if (data.code === 400) {
							resolve(false);
						}
						return data.code ? reject(xhr) : resolve(data);
					};
					xhr.open('POST', `${config.srsUrl}/rtc/v1/publish/`, true);
					xhr.setRequestHeader('Content-type', 'application/json');
					xhr.send(JSON.stringify(data));
				});
			
				console.log(session);
				if (session === false) {
					return false;
				}
				await pc.setRemoteDescription(
					new RTCSessionDescription({
						type: 'answer',
						sdp: session.sdp
					}),
				);
			
				function muteAudio(type) {
					stream.getTracks().forEach(function(track) {
						if (track.kind === 'audio') {
							track.enabled = type ? type : false;
						}
					});
				}
			
				function muteVideo(type) {
					stream.getTracks().forEach(function(track) {
						if (track.kind === 'video') {
							track.enabled = type ? type : false;
						}
					});
				}
				const _this = this
			
				async function unpublish() {
					try {
						stream.getTracks().forEach(function(track) {
							track.stop();
							stream.removeTrack(track);
						});
						// stream.close()
						pc.close();
						setTimeout(()=>{
							_this.myvddata.stream = null
							_this.myvddata = {}
						},1500)
					} catch (e) {
						//TODO handle the exception
					}
				}
			
				const vdata = {
					id: id,
					roomId: roomId,
					pc,
					stream,
					audio: options.audio == false ? false : true,
					video: options.video == false ? false : true,
					videoType: options.videoType ? options.videoType : "environment",
					muteAudio,
					muteVideo,
					unpublish,
				};
			
				this.myvddata = vdata
			
				this.$u.post(`chat/chat/liveroom/lmpubdone`,{
					id:this.id,
					uid:this.uid,
				})
			},
			publishStreamc: async function(options) {
				const id = this.$store.state.user.user.id
				const roomId = 'liveroomlm'+this.uid
				const pc = new RTCPeerConnection(null);
				pc.addTransceiver('audio', {
					direction: 'sendonly'
				});
				pc.addTransceiver('video', {
					direction: 'sendonly'
				});
				const stream = await this.getStreamLoc({
					audio: true,
					video: {
						facingMode: options.videoType ? options.videoType : "environment"
					},
				})
				this.cameraType = options.videoType ? options.videoType : "environment"
				console.log(stream);
				stream.getTracks().forEach(function(track) {
					pc.addTrack(track);
					if (track.kind === 'audio') {
						if (options.audio === false) {
							track.enabled = false;
						}
					}
					if (track.kind === 'video') {
						if (options.video === false) {
							track.enabled = false;
						}
					}
				});
				let offer = await pc.createOffer();
				await pc.setLocalDescription(offer);
			
				let session = await new Promise(function(resolve, reject) {
					let data = {
						api: `${config.srsUrl}/rtc/v1/publish/`,
						tid: id,
						streamurl: `webrtc://${config.ip}/${roomId}/${id}`,
						clientip: null,
						sdp: offer.sdp,
					};
					console.log('Generated offer: ', data);
			
					const xhr = new XMLHttpRequest();
					xhr.onload = function() {
						if (xhr.readyState !== xhr.DONE) return;
						if (xhr.status !== 200) return reject(xhr);
						const data = JSON.parse(xhr.responseText);
						console.log('Got answer: ', data);
						if (data.code === 400) {
							resolve(false);
						}
						return data.code ? reject(xhr) : resolve(data);
					};
					xhr.open('POST', `${config.srsUrl}/rtc/v1/publish/`, true);
					xhr.setRequestHeader('Content-type', 'application/json');
					xhr.send(JSON.stringify(data));
				});
			
				console.log(session);
				if (session === false) {
					return false;
				}
				await pc.setRemoteDescription(
					new RTCSessionDescription({
						type: 'answer',
						sdp: session.sdp
					}),
				);
			
				function muteAudio(type) {
					stream.getTracks().forEach(function(track) {
						if (track.kind === 'audio') {
							track.enabled = type ? type : false;
						}
					});
				}
			
				function muteVideo(type) {
					stream.getTracks().forEach(function(track) {
						if (track.kind === 'video') {
							track.enabled = type ? type : false;
						}
					});
				}
				const _this = this
			
				async function unpublish() {
					try {
						stream.getTracks().forEach(function(track) {
							track.stop();
							stream.removeTrack(track);
						});
						// stream.close()
						pc.close();
						_this.myvddata.stream = null
						_this.myvddata = null
					} catch (e) {
						//TODO handle the exception
					}
				}
			
				const vdata = {
					id: id,
					roomId: roomId,
					pc,
					stream,
					audio: options.audio == false ? false : true,
					video: options.video == false ? false : true,
					videoType: options.videoType ? options.videoType : "environment",
					muteAudio,
					muteVideo,
					unpublish,
				};
			
				this.myvddata = vdata
			},
			getStreamLoc: async function(constraints) {
				if (navigator.mediaDevices.getUserMedia) {
					console.log('最新的标准API', navigator.mediaDevices.getUserMedia);
					const rs = await navigator.mediaDevices.getUserMedia(constraints)
					return rs
				} else if (navigator.webkitGetUserMedia) {
					console.log('webkit核心浏览器');
					const rs = await navigator.webkitGetUserMedia(constraints)
					return rs
				} else if (navigator.mozGetUserMedia) {
					console.log('firfox浏览器');
					const rs = await navigator.mozGetUserMedia(constraints);
					return rs
				} else if (navigator.getUserMedia) {
					console.log('旧版API');
					const rs = await navigator.getUserMedia(constraints);
					return rs
				} else {
					const rs = await navigator.mediaDevices.getUserMedia(constraints)
					return rs
				}
			},
		}
	}
</script>


<style scoped>
	.content {
		display: flex;
		flex-direction: column;
		align-items: center;
		width: 100%;
		height: 100vh;
		justify-content: space-between;
		overflow-y: hidden;
	}

	.btmvg {
		width: 100%;
		display: flex;
		height: 40%;
		background: linear-gradient(to bottom, #33333300, #111111);
		position: fixed;
		left: 0rpx;
		bottom: 0rpx;
		color: white;
		align-items: flex-end;
	}

	.topvg {
		width: 100%;
		display: flex;
		height: 40%;
		background: linear-gradient(to bottom, #111111, #33333300);
		position: fixed;
		left: 0rpx;
		top: 0rpx;
		color: white;
		align-items: flex-start;
		z-index: 99;
	}

	.btnitem {
		width: 120rpx;
		height: 120rpx;
		display: flex;
		align-items: center;
		justify-content: center;
		border-radius: 160rpx;
		background: #cfcfcf55;
	}
</style>